/**
 * 
 */
package com.tech.freak.pyp.rest;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;

import android.util.Log;

/**
 * @author julian
 *
 */
public class RestClient {
	
	private static final String TAG = "RestClient";
    private static final int BUFFER_SIZE = 8192;
	private ArrayList <NameValuePair> params;
    private ArrayList <NameValuePair> headers;

    private String url;

    private int responseCode;
    private String message;
    private String filepath;

    private String response;
	private BasicHttpContext context;
	private BasicHttpParams mHttpParams;
	private InputStream instream;

    public String getResponse() {
        return response;
    }

    public String getErrorMessage() {
        return message;
    }

    public int getResponseCode() {
        return responseCode;
    }

    public InputStream getInstream() {
		return instream;
	}

	public RestClient(String url)
    {
        this.url = url;
        params = new ArrayList<NameValuePair>();
        headers = new ArrayList<NameValuePair>();
    }

    public void AddParam(String name, String value)
    {
        params.add(new BasicNameValuePair(name, value));
    }

    public void AddHeader(String name, String value)
    {
        headers.add(new BasicNameValuePair(name, value));
    }

    public void Execute(RequestMethod method) throws Exception
    {
        switch(method) {
            case GET:
            {
                //add parameters
                String combinedParams = "";
                if(!params.isEmpty()){
                    combinedParams += "?";
                    for(NameValuePair p : params)
                    {
                        String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue(),"UTF-8");
                        if(combinedParams.length() > 1)
                        {
                            combinedParams  +=  "&" + paramString;
                        }
                        else
                        {
                            combinedParams += paramString;
                        }
                    }
                }

                HttpGet request = new HttpGet(url + combinedParams);

                //add headers
                for(NameValuePair h : headers)
                {
                    request.addHeader(h.getName(), h.getValue());
                }

                executeRequest(request, url);
                break;
            }
            case POST:
            {
                HttpPost request = new HttpPost(url);

                //add headers
                for(NameValuePair h : headers)
                {
                    request.addHeader(h.getName(), h.getValue());
                }
                //Add params or a file
                if(!params.isEmpty() && filepath==null){
                    request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
                }else if(filepath!=null){
                	File file = new File(filepath);
                	FileEntity entity = new FileEntity(file, "text/xml; charset=\"UTF-8\"");
                	entity.setChunked(true);
                	request.setEntity(entity);
                }

                executeRequest(request, url);
                break;
            }
        }
    }

    private void executeRequest(HttpUriRequest request, String url)
    {
    	HttpClient client = new DefaultHttpClient(mHttpParams);

        HttpResponse httpResponse;

        try {
            if(context != null){
            	httpResponse = client.execute(request, context);
            }
            else{
            	httpResponse = client.execute(request);
            }
            responseCode = httpResponse.getStatusLine().getStatusCode();
            message = httpResponse.getStatusLine().getReasonPhrase();

            HttpEntity entity = httpResponse.getEntity();

            if (entity != null) {

                instream = entity.getContent();
            	//handle compressed stream
                Header contentEncoding = httpResponse.getFirstHeader("Content-Encoding");
            	if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
            	    instream = new GZIPInputStream(instream);
            	}
            	//put response on a string
                response = convertStreamToString(instream);

                // Closing the input stream will trigger connection release
                instream.close();
            }

        } catch (ClientProtocolException e)  {
            client.getConnectionManager().shutdown();
            Log.e(TAG, e.toString());
        } catch (IOException e) {
            client.getConnectionManager().shutdown();
            Log.e(TAG, e.toString());
        }
    }

	private static String convertStreamToString(InputStream is) {

        BufferedReader reader = new BufferedReader(new InputStreamReader(is), BUFFER_SIZE );
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
    
    public void setCredentials(UsernamePasswordCredentials cred, String AuthServer){
		if (cred != null)
		{
			Log.i(TAG, "Adding credentials ");
			CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
			credentialsProvider.setCredentials(new AuthScope(AuthServer, AuthScope.ANY_PORT),
					cred);
			
			// Adding login info to context
			context = new BasicHttpContext();
			context.setAttribute("http.auth.credentials-provider", credentialsProvider);
		}
    }
    
    public void addFile(String filepath){
    	this.filepath = filepath;
    }

}
